#include <stdio.h>
#include <assert.h>

// 字符串拷贝
char *my_strcpy(char *dest, char *sorc)
{
    assert(dest && sorc);

    char *p = dest;
    while (*dest++ = *sorc++)
    {
        ;
    }

    return p;
}

// 字符串追加
char *my_strcat(char *dest, const char *sorc)
{
    assert(dest && sorc);
    char *p = dest;

    // 找到dest的\0
    while (*(++dest) != '\0')
    {
        ;
    }
    while (*dest++ = *sorc++)
    {
        ;
    }
    return p;
}

// 字符串比较
int my_strcmp(char *arr1, char *arr2)
{
    // 找到不相同的元素
    while (*arr1 == *arr2)
    {
        // 说明两个字符串完全相同 并且走到了末尾
        if (*arr1 == '\0')
            return 0;

        arr1++;
        arr2++;
    }
    return (*arr1 - *arr2);
}

// 找字符串中的子串
char *my_strstr(const char *arr1, const char *arr2)
{
    assert(arr1 && arr2);
    // 定义两个指针
    const char *s1 = arr1; // 遍历arr1
    const char *s2 = arr2; // 遍历arr2
    const char *p = s1;    // 记录arr1遍历的起始位置
    while (*p)
    {
        s2 = arr2; // 新一轮的查找
        s1 = p;    // 更改查找的起始位置
        while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
        {
            s1++;
            s2++;
        }

        // 判断寻找结果
        if (*s2 == '\0')
        {
            return (char *)p;
        }

        p++;
    }

    // 没找到
    return NULL;
}

// 求字符串长度--递归
int my_strlen(char *arr)
{
    if (*arr == '\0')
        return 0;

    return 1 + my_strlen(arr + 1);
}

// memcpy 独立拷贝两块内存空间的数据 模拟实现
void *my_memcpy(void *dest, const void *sorc, size_t n)
{
    assert(dest && sorc);
    void *p = dest;
    while (n--)
    {
        *(char *)dest = *(char *)sorc;
        dest = (char *)dest + 1;
        sorc = (char *)sorc + 1;
    }

    return p;
}

// memmove 重叠拷贝一份内存空间的数据 模拟实现
void *my_memmove(void *dest, const void *sorc, size_t n)
{
    assert(dest && sorc);
    void *p = dest;
    if (dest < sorc)
    {
        // 从前往后拷贝
        while (n--)
        {
            *(char *)dest = *(char *)sorc;
            dest = (char *)dest + 1;
            sorc = (char *)sorc + 1;
        }
    }
    else
    {
        // 从后往前拷贝
        while (n--)
        {
            *((char *)dest + n) = *((char *)sorc + n);
        }
    }

    return p;
}

// memset
void *my_memset(void *buff, int set, int sz)
{
    assert(buff);
    for (int i = 0; i < sz; i++)
    {
        *((char *)buff + i) = set;
    }

    return buff;
}

int main()
{
    // test1
    char arr1[] = "abcdef";
    char arr2[20] = {0};
    my_strcpy(arr2, arr1);
    printf("%s\n", arr2);
    printf("\n");

    // test2
    my_strcat(arr1, "hello"); // 目标空间足够大 目标空间可修改 源字符串包含\0 不能自己追加自己，破坏目标空间的字符串，覆盖掉/0，陷入死循环
    printf("%s\n", arr1);
    printf("\n");

    // test3
    char arr3[] = "abcd";
    char arr4[] = "ab";
    int ret = my_strcmp(arr3, arr4);
    if (ret < 0)
    {
        printf("arr3<arr4\n");
    }
    else if (ret == 0)
    {
        printf("arr3==arr4\n");
    }
    else
    {
        printf("arr3>arr4\n");
    }

    // test4
    char *pret = my_strstr(arr3, arr4);
    if (pret == NULL)
    {
        printf("没找到\n");
    }
    else
    {
        printf("找到了\n");
    }

    // test5
    printf("my_strlen:%d\n", my_strlen("hello"));

    // test6
    int arr5[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int arr6[50] = {0};
    my_memcpy(arr6, arr5, sizeof(arr5));
    for (int i = 0; i < sizeof(arr5) / sizeof(arr5[0]); i++)
    {
        printf("%d ", arr6[i]);
    }
    printf("\n");

    // test7
    int arr7[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    my_memcpy(arr7 + 3, arr7, 20);
    for (int i = 0; i < sizeof(arr7) / sizeof(arr7[0]); i++)
    {
        printf("%d ", arr7[i]);
    }
    printf("\n");

    // test8
    char arr[] = "hello world";
    my_memset(arr, 'x', 11);
    printf("%s\n", arr);
    printf("\n");

    return 0;
}